﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Beacon.SPC
{
    public class SpcData
    {
        #region Attribute
        public class Attribute
        {
            public string Name { get; set; }
            public string Value { get; set; }
        }
        #endregion

        #region Members
        private List<double> _data = new List<double>();

        public List<double> Data { get { return _data; } set { _data = value; } }
        public bool Violated { get; set; }
        public Attribute Attr { get; set; }

        #endregion

        #region Constructor
        public SpcData()
        {
            Violated = false;
        }
        #endregion

        #region Public Function

        public void Add(double d)
        {
            _data.Add(d);
        }

        public int Count()
        {
            return _data.Count;
        }

        public override string ToString()
        {
            string rlt = "SPC Point "
                + " Xbar: " + string.Format("{0:0.####}",XBar) + " Range:" + string.Format("{0:0.####}",Range) + " StdDev: " + string.Format("{0:0.####}",StDev)
                + " MR: " + string.Format("{0:0.####}",MR) + Environment.NewLine;
            return  rlt;
        }

        #endregion

        #region Caculate

        public double XBar 
        {
            get 
            {
                return _data.Average();
            }
        }

        public double Range
        {
            get 
            {
                return _data.Max() - _data.Min();
            }
        }

        public double StDev
        {
            get
            {
                if (_data.Count < 2)
                    return double.NaN;
                double sum = 0, sum2 = 0;
                foreach (double d in _data)
                {
                    sum += d;
                    sum2 += d * d;
                }
                return Math.Sqrt((sum2 - sum * sum / _data.Count) / (_data.Count - 1));
            }
        }

        public double X0
        {
            get
            {
                return _data.Count > 0 ? _data[0] : double.NaN;
            }
        }

        public double MR 
        { 
            get 
            { 
                return _data.Count < 2 ? double.NaN : Math.Abs(_data[0] - _data[1]); 
            } 
        }

        public double U(ScalarInspection inspection)
        {
            if (inspection == null || _data.Count == 0)
                return double.NaN;
            int n = 0;
            foreach (double d in _data)
            {
                if (!inspection.check(d))
                    n++;
            }
            
            return (double)n/_data.Count;
        }

        public double C(ScalarInspection inspection)
        {
            if (inspection == null || _data.Count == 0)
                return double.NaN;
            int n = 0;
            foreach (double d in _data)
            {
                if (!inspection.check(d))
                    n++;
            }

            return (double)n;
        }

        public double P(ScalarInspection inspection)
        {
            if (inspection == null || _data.Count == 0)
                return double.NaN;
            int n = 0;
            foreach (double d in _data)
            {
                if (!inspection.check(d))
                    n++;
            }

            return (double)n;
        }

        public double NP(ScalarInspection inspection)
        {
            if (inspection == null || _data.Count == 0)
                return double.NaN;
            int n = 0;
            foreach (double d in _data)
            {
                if (!inspection.check(d))
                    n++;
            }

            return (double)n;
        }

        #endregion

    }
}
